Conversation
Covers 10 concrete steps: fix todo!() panics, add UniInput conversion helpers, implement arithmetic/comparison/bool for FPy/DPy/RPy, complete integer methods, add float/rational predicates and rounding, create math module for sin/cos/exp/sqrt and gcd/lcm, fix __format__, update type stubs, and add tests. Co-Authored-By: Claude <noreply@anthropic.com>
Choose PyO3 0.24 (not 0.29) because: - 0.24 MSRV is 1.63 — dashu's MSRV 1.68 is preserved - 0.26+ requires MSRV 1.74+ (hard constraint violation per AGENTS.md) - 0.24 has the modern Bound API, IntoPyObject, and stable #[pymodule] form - 0.26+ drops Python 3.7 support Covers all breaking changes: #[pymodule] signature, FromPyObject→extract_bound, #[pyclass(eq, eq_int)], .into_py()→.into_py_any(), and .downcast()→.cast(). Co-Authored-By: Claude <noreply@anthropic.com>
AGENTS.md: Clarify that MSRV policy applies only to core crates (dashu meta-crate and its dependencies: base, int, float, ratio, macros). Secondary crates (dashu-python, benchmark, fuzz tests) are exempt. TODO-python.md: Update Step 0 to target PyO3 0.29 instead of 0.24. Since dashu-python is not bounded by the workspace MSRV, we can use the latest PyO3. Covers all breaking changes through 0.29: - FromPyObject with Borrowed and dual lifetimes (0.27) - .downcast() -> .cast() (0.27) - extension-module feature removed (0.28+) - rust-version bumped to 1.83, requires-python >= 3.8 Co-Authored-By: Claude <noreply@anthropic.com>
Edition 2024 requires Rust >= 1.85. Co-Authored-By: Claude <noreply@anthropic.com>
…rsing dashu-python uses edition 2024 which requires Rust >= 1.85. When the CI runs with Rust 1.68, cargo fails to parse python/Cargo.toml even for workspace-level commands like 'cargo update'. The fix removes the python member from the workspace list via sed before any cargo commands run in the 1.68 job. Co-Authored-By: Claude <noreply@anthropic.com>
parking_lot and lock_api are transitive deps of PyO3, which is only used by dashu-python. Since dashu-python is removed from the workspace in the 1.68 MSRV job, these packages are no longer in the dependency tree and cargo update fails trying to pin them. Also apply cargo fmt. Co-Authored-By: Claude <noreply@anthropic.com>
Integrates dashu-cmplx (complex numbers, #85) and other develop changes.
AGENTS.md: - Add dashu-cmplx to core crates list and workspace structure table - Fix dashu_ratio -> dashu-ratio typo TODO-python.md: - Add dashu-cmplx dependency to Step 0a (Cargo.toml) - Add Step 11: CBig -> CPy complex number bindings - Update Notes for edition 2024, Rust 1.85, and complex crate Co-Authored-By: Claude <noreply@anthropic.com>
Restore develop's tests.yml verbatim (check job was moved to build.yml). Apply dashu-python fixes to build.yml: - Remove dashu-python from workspace before cargo commands (Rust 1.68) - Drop parking_lot/lock_api pinning (only in dashu-python dep tree) - Drop --exclude dashu-python (no longer a workspace member after sed) Co-Authored-By: Claude <noreply@anthropic.com>
FPy/DPy/CPy now wrap CachedFBig/CachedCBig (memoize pi/ln2/ln10 via ConstCache) instead of bare FBig/CBig. Rationals/integers stay uncached. Key consequences documented: - CachedFBig/CachedCBig are !Send + !Sync (Rc<RefCell<ConstCache>>), so FPy/DPy/CPy must use #[pyclass(unsendable)] -- incompatible with free-threaded Python (no-GIL, PEP 703). - UPy/IPy/RPy keep default Send #[pyclass] (no transcendental ops). - Conversion helpers (into_fpy/dpy/cpy) build cached wrappers via From/FromStr/TryFrom (each attaches a fresh cache). - Methods not yet mirrored on the cached types (trunc/floor/ceil/fract/ round/split_at_point/with_base/to_decimal/nth_root/hypot) delegate through .as_fbig()/.as_cbig() and wrap back with a fresh cache. - Cache-sharing rule: binary ops preserve LHS cache; fresh-cache ops are acceptable where no constant is needed. Updates Architecture, Step 0d2 (wrapper types), Step 2 (convert.rs helpers), Step 6 (predicates/rounding delegation), Step 11 (CPy), smoke test, and Notes. Co-Authored-By: Claude <noreply@anthropic.com>
Instead of wrapping CachedFBig/CachedCBig (which are !Send+!Sync and hide their cache behind pub(crate)), FPy/DPy/CPy now wrap bare FBig/CBig and the module owns a single thread_local ConstCache. Transcendentals route through the panic-free Context layer (ctx.sin(repr, cache) -> FpResult) and map FpError to Python exceptions: Overflow/Underflow -> signed inf/zero, InfiniteInput/OutOfDomain -> ValueError, Indeterminate -> ZeroDivisionError. This replaces the convenience-layer panics that surfaced as session-crashing pyo3_runtime.PanicException (BaseException, not Exception). Wins vs the CachedFBig plan: - All wrappers Send+Sync -> no #[pyclass(unsendable)] - Free-threaded Python (no-GIL) compatible (per-thread cache) - Clean Python exceptions on domain errors - One base-free cache serves FPy (base 2), DPy (base 10), CPy (complex) - Keep all FBig/CBig operator trait impls (no Repr surgery) Plan changes: Architecture rewrite, Step 0d2 (bare types, no unsendable), new Step 2c (cache.rs module), Step 6 transcendentals via Context, Step 11 CPy via complex Context, updated conversions/Notes. Arithmetic still uses operator impls (infinite-input/0-0 panic caveat noted as follow-up). Co-Authored-By: Claude <noreply@anthropic.com>
Step 2b (constructor broadening): FBig/DBig/RBig/CBig __new__ now accept any Python number (int, float, Decimal, Fraction, complex) via permissive construct_* helpers — distinct from the strict into_* arithmetic dispatch (which matches Python's own 1.5 + Decimal TypeError rule). Decimal/Fraction -> FBig/DBig are exact-only; lossy conversion goes through to_float (6c). Step 6c (cross-type conversions): expose FBig.to_decimal/to_binary (base 2<->10), FBig.to_rational (exact), RBig.to_float/to_decimal (lossy, correctly rounded, explicit precision). Adds a full conversion matrix between FPy/DPy/RPy/UPy/IPy and Python native types. Co-Authored-By: Claude <noreply@anthropic.com>
Upgrade PyO3 0.20 → 0.29 (Bound API, IntoPyObject, edition 2024, rust-version 1.85; requires-python >=3.8) and implement every step of python/TODO-python.md: - FBig/DBig/RBig: arithmetic, comparison, __bool__, predicates, rounding, precision, transcendentals, and cross-type conversions (to_decimal/to_binary/ to_rational/to_float). Broadened __new__ accepts any Python number. - UBig/IBig: number theory (sqrt/cbrt/nth_root/gcd/gcd_ext/ilog/...), bit ops, __floordiv__/__divmod__, and in-place operators. Fixed the todo!() panics in __mod__/__pow__. - CBig (new): complex bindings wrapping a bare CBig<Zero,2> with arithmetic, real/imag, conj/proj/norm/abs/arg, and transcendentals. - A module-level `math` API and a `dashu.Cache` handle. - Transcendentals are panic-free: routed through a shared thread-local ConstCache + the panic-free Context layer; domain errors raise ValueError and 0/0 raises ZeroDivisionError instead of crashing the session. All wrappers are Send+Sync (no #[pyclass(unsendable)]). FBig(f64) now constructs at f64's native precision so transcendentals are well-defined. Verified with maturin develop + 29 passing pytest tests; 0 clippy warnings, fmt clean. Co-Authored-By: Claude <noreply@anthropic.com>
powi/from_parts/ilog took dashu-pyclass references (e.g. &IPy), so passing a plain Python int raised "TypeError: 'int' object is not an instance of 'IBig'". Switch them to UniInput<'_> and add UniInput::into_ibig (mirroring into_ubig), so FBig(12).powi(300), RBig.from_parts(1, 3), UBig(256).ilog(2), etc. work. Updated the stub and added regression tests. Co-Authored-By: Claude <noreply@anthropic.com>
…ional.rs All numeric function/method arguments now go through UniInput so a plain Python int/float works directly — dashu.sqrt(9.0), FBig(2).powi(300), UBig(12).gcd(8), UBig(n) += 5, RBig.from_parts(1, 3), etc. (into_fpy now builds floats at f64's native precision so transcendentals are well-defined). Rewrote the test suite to use native Python types throughout. Renamed python/src/ratio.rs to rational.rs. Also untracked the tests/__pycache__ artifacts and added a .gitignore. Co-Authored-By: Claude <noreply@anthropic.com>
- UBig/IBig: delegate to Python int.__format__ (arbitrary precision, all integer
presentation types: b/o/d/x/X/c/n, sign/width/align/fill/zero/grouping).
- FBig/DBig: new format.rs renders in decimal (FBig converts via to_decimal) with
e/E/f/g/n/% types, precision, sign, width, align, fill, zero-pad, grouping, and
normalizes dashu's bare exponent to CPython's `e+00` form. Arbitrary precision is
preserved: f"{FBig(2).with_precision(200).exp():.20e}" -> 7.38905609893065022723e+00.
- RBig: empty spec -> "num/den"; float specs render via a high-precision conversion.
- CBig: applies the spec to both parts -> "(re+imj)".
Added tests/test_format.py. 34/34 tests pass, 0 clippy warnings, fmt clean.
Co-Authored-By: Claude <noreply@anthropic.com>
str()/print() previously used dashu's Display, which prints in the number's base — so an FBig (base 2) printed in BINARY (str(FBig(2.0)) == '10', str(FBig(0.1)) was a long binary expansion). Route __str__ through the decimal formatter (__format__ path), converting via to_decimal, so str(FBig(2.0)) == '2', str(FBig(0.1)) == '0.1', and the output reflects the value's precision in decimal. DBig was already decimal; routed through the same path for consistency. Co-Authored-By: Claude <noreply@anthropic.com>
- FBig (base 2) now renders in hexadecimal by default (str/format/''/'a'/'A'), via dashu's LowerHex/UpperHex — lossless, no base-2->base-10 conversion rounding (str(FBig(1.5)) == '0x3p-1'). Decimal presentations 'e'/'f'/'g' still convert to base 10. DBig stays decimal-native. - When no precision is given for 'e'/'E', show the value's full native precision (significant digits) instead of CPython's fixed 6 — format(DBig(1.23) .with_precision(100).powi(100000), 'e') now prints all 100 digits. Use '.6e' for the old 6-digit default. Added format_fbig_hex; updated tests. Co-Authored-By: Claude <noreply@anthropic.com>
RBig.__format__ converted to a decimal float at exactly the requested precision, so e.g. format(RBig(1)/3, '.20e') printed a spurious trailing 0 (only 20 sig digits were available but 21 were requested). Convert with a 16-digit guard when a precision is given so the printed digits are correctly rounded. (No-precision default stays 53.) Note: format(r, '20e') is WIDTH 20 (Python spec), not precision — use '.20e' for 20 fraction digits. The digit count for a bare 'e' is the native default. Co-Authored-By: Claude <noreply@anthropic.com>
python/README.md is now the canonical usage doc (rendered by PyPI); the new
guide/src/python.md just does {{#include ../../python/README.md}} so the guide
and the PyPI README stay in sync from a single source. SUMMARY.md lists the page.
The doc briefly covers the types, the mirrored operations (cross-type arithmetic,
integer number theory / bit ops, float/rational/complex transcendentals, the
panic-free error model + shared constant cache, conversions, and the module-level
math API), and the supported formatting (Python mini-language; FBig prints hex by
default, RBig prints the exact fraction). All code examples were verified.
Co-Authored-By: Claude <noreply@anthropic.com>
Every step of the plan has been implemented and verified (PyO3 0.20->0.29,
todo!() panic fixes, UniInput conversion helpers + broadened constructors, the
global cache module, FBig/DBig/RBig arithmetic+comparison+bool, integer number
theory / bit ops / in-place ops, float/rational predicates + transcendentals +
cross-type conversions, the math module, full __format__ mini-language, complex
CBig bindings, stubs, tests, and the guide page). Beyond the plan, native Python
numbers are now accepted throughout, FBig prints in hex by default, and float 'e'
defaults to native precision.
The only plan item not implemented is Step 5d's full IBig bit-slice parity
(slice __getitem__/__setitem__/__delitem__); IPy keeps single-bit read only, as in
the original binding ("very limited capabilities") — bit-slicing a signed integer
is ill-defined. The one remaining engineering follow-up (route bare FBig/CBig
arithmetic through the Context layer so infinite-input / 0/0 raise instead of
panicking) is already noted in CHANGELOG.md.
Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.